package advanced

import (
	"context"
	//"encoding/json"

	. "gitee.com/liukexing/isrn/api"
)

type P2pCommand struct {
	Shell
}

type P2PListener struct {
	Protocol string
	Address  string
}

type P2PListeners struct {
	Listeners []P2PListener
}

func (s *P2pCommand) ListenerClose(protocol string) (string, error) {
	cmdargs := []string{protocol}

	out := ""
	err := s.Request("p2p/listener/close", cmdargs...).Option("all", true).Exec(context.Background(), out)
	if err != nil {
		return "", err
	}
	return out, nil

	//	req := s.NewRequest(context.Background(), "p2p/listener/close", protocol)

	//	resp, err := req.Send(s.HttpCli)
	//	if err != nil {
	//		return "", err
	//	}
	//	defer resp.Close()

	//	if resp.Error != nil {
	//		return "", resp.Error
	//	}

	//	return "", nil
}

func (s *P2pCommand) ListenerCloseAll() (string, error) {

	cmdargs := []string{}

	out := ""
	err := s.Request("p2p/listener/close", cmdargs...).Option("all", true).Exec(context.Background(), out)
	if err != nil {
		return "", err
	}
	return out, nil

	//	req := s.NewRequest(context.Background(), "p2p/listener/close")
	//	req.Opts["all"] = "true"

	//	resp, err := req.Send(s.HttpCli)
	//	if err != nil {
	//		return "", err
	//	}
	//	defer resp.Close()

	//	if resp.Error != nil {
	//		return "", resp.Error
	//	}

	//	return "", nil
}

/*
USAGE
  ipfs p2p listener ls - List active p2p listeners.

SYNOPSIS
  ipfs p2p listener ls [--headers | -v]

OPTIONS

  -v, --headers bool - Print table headers (HandlerID, Protocol, Local, Remote). Default: false.
*/
func (s *P2pCommand) ListenerLs() (*P2PListeners, error) {
	cmdargs := []string{}

	out := &P2PListeners{}
	err := s.Request("p2p/listener/ls", cmdargs...).Exec(context.Background(), out)
	if err != nil {
		return nil, err
	}
	return out, nil

	//	req := s.NewRequest(context.Background(), "p2p/listener/ls")

	//	resp, err := req.Send(s.HttpCli)
	//	if err != nil {
	//		return nil, err
	//	}
	//	defer resp.Close()

	//	if resp.Error != nil {
	//		return nil, resp.Error
	//	}
	//	out := &P2PListeners{}
	//	err = json.NewDecoder(resp.Output).Decode(out)
	//	if err != nil {
	//		return nil, err
	//	}

	//	return out, nil
}

/*
USAGE
  ipfs p2p listener open <Protocol> <Address> - Forward p2p connections to a network multiaddr.

SYNOPSIS
  ipfs p2p listener open [--] <Protocol> <Address>

ARGUMENTS

  <Protocol> - Protocol identifier.
  <Address>  - Request handling application address.

DESCRIPTION

  Register a p2p connection handler and forward the connections to a specified
  address.

  Note that the connections originate from the ipfs daemon process.
*/
func (s *P2pCommand) ListenerOpen(protocol, address string) (*P2PListener, error) {

	cmdargs := []string{protocol, address}

	out := &P2PListener{}
	err := s.Request("p2p/listener/open", cmdargs...).Exec(context.Background(), out)
	if err != nil {
		return nil, err
	}
	return out, nil

	//	cmdargs := []string{protocol, address}

	//	req := s.NewRequest(context.Background(), "p2p/listener/open", cmdargs...)

	//	resp, err := req.Send(s.HttpCli)
	//	if err != nil {
	//		return nil, err
	//	}
	//	defer resp.Close()

	//	if resp.Error != nil {
	//		return nil, resp.Error
	//	}
	//	out := &P2PListener{}
	//	err = json.NewDecoder(resp.Output).Decode(out)
	//	if err != nil {
	//		return nil, err
	//	}

	//	return out, nil
}

/*
USAGE
  ipfs p2p stream - P2P stream management.

SYNOPSIS
  ipfs p2p stream

DESCRIPTION

  Create and manage p2p streams

SUBCOMMANDS
  ipfs p2p stream close [<HandlerID>]                    - Close active p2p stream.
  ipfs p2p stream dial <Peer> <Protocol> [<BindAddress>] - Dial to a p2p listener.
  ipfs p2p stream ls                                     - List active p2p streams.

  Use 'ipfs p2p stream <subcmd> --help' for more information about each command.
*/
/*
{"Streams":[{"HandlerID":"10","Protocol":"/p2p/Route","LocalPeer":"Qmdqtg1yAVy8JUsahk6uedQVpK5reehnkKFgTqWMaoA3HT","LocalAddress":"/ip4/127.0.0.1/tcp/10000","RemotePeer":"QmP4nwmBgHRq3m7Qt93PBWQestZpjELasEFmToHknZ7gHg","RemoteAddress":"/ip4/127.0.0.1/tcp/49610"}]}
*/
type P2pStream struct {
	HandlerID     int
	Protocol      string
	LocalPeer     string
	LocalAddress  string
	RemotePeer    string
	RemoteAddress string
}

type P2pStreams struct {
	Streams []interface{}
}

/*
USAGE
  ipfs p2p stream close [<HandlerID>] - Close active p2p stream.

SYNOPSIS
  ipfs p2p stream close [--all | -a] [--] [<HandlerID>]

ARGUMENTS

  [<HandlerID>] - Stream HandlerID

OPTIONS

  -a, --all bool - Close all streams. Default: false.
*/

/*
USAGE
  ipfs p2p stream dial <Peer> <Protocol> [<BindAddress>] - Dial to a p2p listener.

SYNOPSIS
  ipfs p2p stream dial [--] <Peer> <Protocol> [<BindAddress>]

ARGUMENTS

  <Peer>          - Remote peer to connect to
  <Protocol>      - Protocol identifier.
  [<BindAddress>] - Address to listen for connection/s (default: /ip4/127.0.0.1/tcp/0).

DESCRIPTION

  Establish a new connection to a peer service.

  When a connection is made to a peer service the ipfs daemon will setup one
  time TCP listener and return it's bind port, this way a dialing application
  can transparently connect to a p2p service.
*/
func (s *P2pCommand) StreamDial(peer, protocol, address string) (*P2PListener, error) {
	cmdargs := []string{peer, protocol, address}

	out := &P2PListener{}
	err := s.Request("p2p/stream/dial", cmdargs...).Exec(context.Background(), out)
	if err != nil {
		return nil, err
	}
	return out, nil

	//	cmdargs := []string{peer, protocol, address}

	//	req := s.NewRequest(context.Background(), "p2p/stream/dial", cmdargs...)

	//	resp, err := req.Send(s.HttpCli)
	//	if err != nil {
	//		return nil, err
	//	}
	//	defer resp.Close()

	//	if resp.Error != nil {
	//		return nil, resp.Error
	//	}
	//	out := &P2PListener{}
	//	err = json.NewDecoder(resp.Output).Decode(out)
	//	if err != nil {
	//		return nil, err
	//	}

	//	return out, nil
}

/*
USAGE
  ipfs p2p stream ls - List active p2p streams.

SYNOPSIS
  ipfs p2p stream ls [--headers | -v]

OPTIONS

  -v, --headers bool - Print table headers (HagndlerID, Protocol, Local, Remote). Default: false.
*/
